package data

import (
	"time"

	"rosesservice/internal/conf"
	gormlog "rosesservice/pkg/log"

	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-redis/redis/v8"
	"github.com/google/wire"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	logleve "gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
)

var ProviderSet = wire.NewSet(
	NewCommon,
	NewAccount,
	NewDB,
	NewRbacSchema,
	NewAccountSchema,
	NewArticles,
	NewBasic,
	NewGRPCClient,
)

// Data .
type Data struct {
	db  *gorm.DB
	rdb *redis.Client
}

// NewData .
func NewData(c *conf.Data) (*Data, func(), error) {
	dsn := c.Database.Source + "?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
	newLogger := gormlog.NewGormLogger("./logs/project.log", []interface{}{"service.name", "database"}, logleve.Error)
	db, errDb := gorm.Open(mysql.Open(dsn), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			// 使用单数表名，启用该选项，此时，`User` 的表名应该是 `t_user`,加S
			SingularTable: true,
		},
		// 对于写操作（创建、更新、删除），为了确保数据的完整性，GORM 会将它们封装在事务内运行。但这会降低性能，你可以在初始化时禁用这种方式
		SkipDefaultTransaction: true,
		Logger:                 newLogger,
	})
	if errDb != nil {
		log.Error(errDb.Error())
		return nil, nil, errDb
	}
	sqlDB, err := db.DB()
	if err != nil {
		log.Error(errDb.Error())
		return nil, nil, errDb
	}
	// 设置连接池
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetMaxIdleConns(20)
	// 可以复用的最大时间
	sqlDB.SetConnMaxLifetime(1700 * time.Second)
	d := &Data{
		db:  db,
		rdb: newRedisdb(c),
	}
	cleanup := func() {
		log.Info("message closing the data resources")
		if err := sqlDB.Close(); err != nil {
			log.Error(err)
		}
	}
	return d, cleanup, nil
}

func newRedisdb(c *conf.Data) *redis.Client {
	client := redis.NewClient(&redis.Options{
		Addr:     c.Redis.Addr,
		Password: c.Redis.Password,
		DB:       1,
	})

	return client
}
